package edu.study.common.util;

import com.google.common.base.Charsets;
import edu.study.common.util.log.Loggers;
import org.apache.http.*;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class HttpUtils {
    
    private static final int TIMEOUT_MILLIS = 10 * 1000;
    public static Logger accesslogger = Loggers.service;
    private static CloseableHttpClient httpclient;
    private static RequestConfig requestConfig;

    static {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(100);
        connectionManager.setDefaultMaxPerRoute(100);

        //HttpHost proxy = new HttpHost("172.17.138.155", 7000);
        //DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
        httpclient = HttpClientBuilder.create()
                .setConnectionManager(connectionManager)
                //.setRoutePlanner(routePlanner)
                .setUserAgent("auto").setRedirectStrategy(new RedirectStrategy() {

                    @Override
                    public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
                        //
                        return false;
                    }

                    @Override
                    public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
                        //
                        return null;
                    }
                }).build();

        requestConfig = RequestConfig.custom()
                .setSocketTimeout(TIMEOUT_MILLIS)
                .setConnectTimeout(TIMEOUT_MILLIS)
                .setConnectionRequestTimeout(TIMEOUT_MILLIS)
                .build();
    }

    private static void setTimeout(HttpRequestBase request) {
        //ConnectTimeout： 链接建立的超时时间；
        //SocketTimeout：响应超时时间，超过此时间不再读取响应；
        //ConnectionRequestTimeout： http clilent中从connetcion pool中获得一个connection的超时时间；
//        RequestConfig requestConfig = RequestConfig.custom()
//                .setSocketTimeout(TIMEOUT_MILLIS)
//                .setConnectTimeout(TIMEOUT_MILLIS)
//                .setConnectionRequestTimeout(TIMEOUT_MILLIS)
//                .build();

        request.setConfig(requestConfig);
    }

    public static CloseableHttpResponse get(String url) throws IOException {
        return get(url, null);
    }

    public static CloseableHttpResponse get(String url, Map<String, String> params) throws IOException {
        if (params != null && params.size() > 0) {
            char firstChar = '?';
            if (url.contains("?")) {
                firstChar = '&';
            }

            StringBuilder sb = new StringBuilder(url + firstChar);
            for (Map.Entry<String, String> entry : params.entrySet()) {
                sb.append(entry.getKey());
                sb.append('=');
                sb.append(entry.getValue());
                sb.append('&');
            }
            sb.deleteCharAt(sb.length() - 1);

            url = sb.toString();
        }

        HttpGet request = new HttpGet(url);
        setTimeout(request);

        String uuid = UUID.randomUUID().toString();
        accesslogger.info("[" + uuid + "] " + "[request]: " + request.getRequestLine().getUri());
        CloseableHttpResponse response = httpclient.execute(request);
        accesslogger.info("[" + uuid + "] " + "[response]: " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase());

        return response;
    }

    public static String getOkResponseText(String url) throws IOException {
        CloseableHttpResponse response = HttpUtils.get(url);
        try {
            HttpUtils.checkStatusOk(response);

            HttpEntity entity = response.getEntity();
            String html = EntityUtils.toString(entity, Charsets.UTF_8);

            return html;

        } finally {
            response.close();
        }
    }

    public static CloseableHttpResponse post(String url, Map<String, String> params, int timeout) throws IOException {
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
        HttpPost request = new HttpPost(url);
        setTimeout(request);
        request.setEntity(entity);

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(timeout)
                .setConnectTimeout(timeout)
                .setConnectionRequestTimeout(timeout)
                .build();
        request.setConfig(requestConfig);

        String uuid = UUID.randomUUID().toString();
        //accesslogger.info("[" + uuid + "] " + "[request]: " + request.getRequestLine().getUri() + " - " + EntityUtils.toString(entity, Charsets.UTF_8));
        CloseableHttpResponse response = httpclient.execute(request);
        //accesslogger.info("[" + uuid + "] " + "[response]: " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase());

        return response;
    }

    public static CloseableHttpResponse post(String url, Map<String, String> params) throws IOException {
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
        HttpPost request = new HttpPost(url);
        setTimeout(request);
        request.setEntity(entity);

        String uuid = UUID.randomUUID().toString();
        //accesslogger.info("[" + uuid + "] " + "[request]: " + request.getRequestLine().getUri() + " - " + EntityUtils.toString(entity, Charsets.UTF_8));
        CloseableHttpResponse response = httpclient.execute(request);
        //accesslogger.info("[" + uuid + "] " + "[response]: " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase());

        return response;
    }

    public static CloseableHttpResponse post(String url, String body, int timeout) throws IOException {
        StringEntity entity = new StringEntity(body, Consts.UTF_8);
        HttpPost request = new HttpPost(url);
        setTimeout(request);
        request.setEntity(entity);

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(timeout)
                .setConnectTimeout(timeout)
                .setConnectionRequestTimeout(timeout)
                .build();
        request.setConfig(requestConfig);

        String uuid = UUID.randomUUID().toString();
        //accesslogger.info("[" + uuid + "] " + "[request]: " + request.getRequestLine().getUri() + " - " + EntityUtils.toString(entity, Charsets.UTF_8));
        CloseableHttpResponse response = httpclient.execute(request);
        //accesslogger.info("[" + uuid + "] " + "[response]: " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase());

        return response;
    }

    public static CloseableHttpResponse post(String url, String body) throws IOException {
        StringEntity entity = new StringEntity(body, Consts.UTF_8);
        HttpPost request = new HttpPost(url);
        setTimeout(request);
        request.setEntity(entity);

        String uuid = UUID.randomUUID().toString();
        //accesslogger.info("[" + uuid + "] " + "[request]: " + request.getRequestLine().getUri() + " - " + EntityUtils.toString(entity, Charsets.UTF_8));
        CloseableHttpResponse response = httpclient.execute(request);
        //accesslogger.info("[" + uuid + "] " + "[response]: " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase());

        return response;
    }

    public static void checkStatusOk(CloseableHttpResponse response) {
        int status = response.getStatusLine().getStatusCode();
        if (status != HttpStatus.SC_OK) {
            throw new RuntimeException("Unexpected response status: " + status);
        }
    }
    public static CloseableHttpResponse postExJson(String url, String body) throws IOException {
        StringEntity entity = new StringEntity(body, Consts.UTF_8);
        HttpPost request = new HttpPost(url);
        entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
        setTimeout(request);
        request.setEntity(entity);

        String uuid = UUID.randomUUID().toString();
        //accesslogger.info("[" + uuid + "] " + "[request]: " + request.getRequestLine().getUri() + " - " + EntityUtils.toString(entity, Charsets.UTF_8));
        CloseableHttpResponse response = httpclient.execute(request);
        //accesslogger.info("[" + uuid + "] " + "[response]: " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase());

        return response;
    }

    public static CloseableHttpResponse postExJson(String url, String body, int timeout) throws IOException {
        StringEntity entity = new StringEntity(body, Consts.UTF_8);
        HttpPost request = new HttpPost(url);
        entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
        setTimeout(request);
        request.setEntity(entity);

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(timeout)
                .setConnectTimeout(timeout)
                .setConnectionRequestTimeout(timeout)
                .build();
        request.setConfig(requestConfig);

        String uuid = UUID.randomUUID().toString();
        //accesslogger.info("[" + uuid + "] " + "[request]: " + request.getRequestLine().getUri() + " - " + EntityUtils.toString(entity, Charsets.UTF_8));
        CloseableHttpResponse response = httpclient.execute(request);
        //accesslogger.info("[" + uuid + "] " + "[response]: " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase());

        return response;
    }

    public static CloseableHttpResponse postExJson(String url, String body, Map<String, String> headerMap) throws IOException {
        StringEntity entity = new StringEntity(body, Consts.UTF_8);
        HttpPost request = new HttpPost(url);
        entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
        setTimeout(request);
        request.setEntity(entity);
        if (headerMap != null) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                request.setHeader(entry.getKey(), entry.getValue());
            }
        }

        String uuid = UUID.randomUUID().toString();
        //accesslogger.info("[" + uuid + "] " + "[request]: " + request.getRequestLine().getUri() + " - " + EntityUtils.toString(entity, Charsets.UTF_8));
        CloseableHttpResponse response = httpclient.execute(request);
        //accesslogger.info("[" + uuid + "] " + "[response]: " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase());

        return response;
    }

    public static void main(String[] args) throws Exception {
//        String param = " {\"transdate\":\"20180503\",\"transtime\":\"000000\",\"amount\":300034,\"ccy\":\"156\",\"custId\":\"8888\",\"TransId\":\"100004\",\"mer_seqno\":\"LOAN_201805ss0ds11421sss20632ss9049\",\"cardinfoId\":\"4549\",\"trans_priamt\":0,\"trans_interamt\":0,\"trans_fee\":0,\"mer_id\":\"S0010001\",\"product_id\":\"8888\",\"channelID\":\"8888\",\"openID\":\"8888\"}";
//        CloseableHttpResponse httpResp = HttpUtils.post("http://payment.sit.sccfc.vip:8080/payment/jsmain", param);
//        HttpEntity entity = httpResp.getEntity();
//        String body = EntityUtils.toString(entity, Charsets.UTF_8);
//        System.out.println(body);
        
        String param = "{\"merchKey\": \"EDF033076ED83570314FEFF015136079\",\"productCode\": \"TEST_PRO_A\",\"ruleCode\": \"TEST_PRO_A1001\",\"applyNo\": \"TEST_002\"}";
        CloseableHttpResponse httpResp = HttpUtils.postExJson("http://159.138.64.34:8080/api/decision_apply/apply_by_merch", param);
        HttpEntity entity = httpResp.getEntity();
        String body = EntityUtils.toString(entity, Charsets.UTF_8);
        System.out.println(body);
        
        
    }
}
